package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.CandidateTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.TaskLinkStatusEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.BaseProcessService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.SyncProcessTaskProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.TurnTaskValidator;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpDispatchWorkItemDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.CommentTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowProcessInstanceOperateTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.FlowTaskInstApproverVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.TurnTaskVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.UserInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: liyang
 * @date: 2021/12/17 19:54
 */
@Service
public class FlowTurnTaskServiceImpl extends BaseProcessService implements FlowTurnTaskService {


    @Autowired
    private FlowTaskService flowTaskService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private UserService userService;

    @Autowired
    private FlowProcessInstanceOperateTraceRepository flowProcessInstanceOperateTraceRepository;

    @Autowired
    private SyncProcessTaskProcessor syncProcessTaskProcessor;

    @Autowired
    private FlowTaskInstApproverRepository flowTaskInstApproverRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult turnTask(HttpDispatchWorkItemDto httpDispatchWorkItemDto) {

        TurnTaskValidator turnTaskValidator = new TurnTaskValidator(taskService);
        TurnTaskValidator.ValidatorResult validatorResult = turnTaskValidator.validate(httpDispatchWorkItemDto);
        if (!validatorResult.isSuccess()){
            return ResponseResult.fail(validatorResult.getErrorCode(),validatorResult.getErrorMsg());
        }

        User user = userRepository.getUserWithOrgByCodeFromUserCenter(httpDispatchWorkItemDto.getParticipantId());
        if (Objects.isNull(user)){
            return ResponseResult.fail(ErrorCode.USER_NOT_EXIST.errCode(),ErrorCode.USER_NOT_EXIST.errMessage());
        }
        TurnTaskVo turnTaskVo = new TurnTaskVo();
        turnTaskVo.setTaskId(httpDispatchWorkItemDto.getWorkItemId());
        turnTaskVo.setTurnToUserCode(httpDispatchWorkItemDto.getTurnToUserCode());
        turnTaskVo.setComment(httpDispatchWorkItemDto.getComment());
        turnTaskVo.setUserCode(httpDispatchWorkItemDto.getParticipantId());
        return flowTaskService.dealTurnTask(turnTaskVo,user);
    }

    @Override
    public ResponseResult turnTaskNonUserCheck(HttpDispatchWorkItemDto httpDispatchWorkItemDto) {
        //不校验用户
        TurnTaskValidator turnTaskValidator = new TurnTaskValidator(taskService,false);
        TurnTaskValidator.ValidatorResult validatorResult = turnTaskValidator.validate(httpDispatchWorkItemDto);
        if (!validatorResult.isSuccess()){
            return ResponseResult.fail(validatorResult.getErrorCode(),validatorResult.getErrorMsg());
        }

        if (StringUtils.isBlank(httpDispatchWorkItemDto.getComment())){
            return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(),"转办不校验用户接口，需传入转办说明[comment]");
        }

        Task task = taskService.createTaskQuery().taskId(httpDispatchWorkItemDto.getWorkItemId()).singleResult();

        TurnTaskVo turnTaskVo = new TurnTaskVo();
        turnTaskVo.setTaskId(httpDispatchWorkItemDto.getWorkItemId());
        turnTaskVo.setTurnToUserCode(httpDispatchWorkItemDto.getTurnToUserCode());
        turnTaskVo.setComment(httpDispatchWorkItemDto.getComment());

        if (StringUtils.isNotBlank(task.getAssignee())){
            turnTaskVo.setUserCode(task.getAssignee());
        }else{
            List<IdentityLink> identityLinkList =  taskService.getIdentityLinksForTask(task.getId());
            if (CollectionUtils.isNotEmpty(identityLinkList)){
                for (IdentityLink identityLink : identityLinkList) {
                    if (StringUtils.isNotBlank(identityLink.getUserId())
                            && (Objects.equals(identityLink.getType(),"STA")
                                || Objects.equals(identityLink.getType(),"candidate"))){
                        turnTaskVo.setUserCode(identityLink.getUserId());
                        break;
                    }
                }
            }
        }
        return turnTask(task,turnTaskVo);
    }


    @Override
    public ResponseResult turnTask(Task task,TurnTaskVo turnTaskVo){
        String lastComment = TaskLinkStatusEnum.TRANSFER.getDesc();
        if (StringUtils.isNotBlank(turnTaskVo.getComment())){
            this.addComment(task.getId(),turnTaskVo.getUserCode(),task.getProcessInstanceId(), CommentTypeEnum.ZB.getName(),turnTaskVo.getComment());
            lastComment = taskService.getProcessInstanceComments(task.getProcessInstanceId()).get(0).getId();
        }

        User turnToUser = userRepository.getUserWithOrgByCodeFromUserCenter(turnTaskVo.getTurnToUserCode());
        if (Objects.isNull(turnToUser)){
            return ResponseResult.fail(ErrorCode.TURN_TO_USER_NOT_EXIST.errCode(),ErrorCode.TURN_TO_USER_NOT_EXIST.errMessage());
        }

        //1.转办
        taskService.setAssignee(task.getId(), turnTaskVo.getTurnToUserCode());
        if (StringUtils.isNotBlank(turnTaskVo.getUserCode())){
            taskService.setOwner(task.getId(), turnTaskVo.getUserCode());
            taskService.deleteUserIdentityLink(task.getId(), turnTaskVo.getUserCode(), CandidateTypeEnum.STA.getCode());
        }
        //如果在转办之前的操作是委派，则更新委派任务的处理人为转办后的人
        String parentTaskId = task.getParentTaskId();
        if (StringUtils.isNoneBlank(parentTaskId)){
            Task parentTask = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
            if (Objects.nonNull(parentTask)){
                //更新原委派人为转办后的人
                parentTask.setAssignee(turnTaskVo.getTurnToUserCode());
                taskService.saveTask(parentTask);
            }
        }

        //修改转办之后的操作人
        updateTaskTrace(task.getId(), turnTaskVo.getTurnToUserCode(),turnTaskVo.getUserCode());
        // 转办记录
        User fromUser = userRepository.getUserWithOrgByCodeFromUserCenter(turnTaskVo.getUserCode());
        FlowProcessInstanceOperateTraceVo operateTrace = new FlowProcessInstanceOperateTraceVo(TaskLinkStatusEnum.TRANSFER.getCode(),
                task.getProcessInstanceId(), task.getId(), turnTaskVo.getUserCode(), fromUser.getUserName(), lastComment);
        flowProcessInstanceOperateTraceRepository.insertProcessInstanceOperateTrace(operateTrace);
        // 转办成功,同步更新该任务的处理人以及是否转办标识
        this.syncDataBySceneAndUser(turnTaskVo.getTaskId(), turnTaskVo.getTurnToUserCode(), Boolean.TRUE);
        return ResponseResult.success("转办成功");
    }


    @Override
    public void updateTaskTrace(String taskId, String turnToUserCode,String operatorCode) {
        //修改任务状态
        FlowTaskTraceVo taskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(taskId);
        if (Objects.isNull(taskTrace)) {
            return;
        }
        taskTrace.setUpdateTime(new Date());
        // 查询流程组件获取单个用户对象信息
        UserInfo userInfo = userService.getUserInfoObj(turnToUserCode);
        taskTrace.setOperator(userInfo == null ? "" : userInfo.getUserName());
        taskTrace.setOperatorCode(turnToUserCode);
        flowTaskTraceRepository.updateTaskTraceById(taskTrace);

        //修改创建任务时保存的审批人信息
        List<FlowTaskInstApproverVo> approverVos = flowTaskInstApproverRepository.selectListByTaskId(taskId);
        if (Objects.isNull(approverVos) || StringUtils.isEmpty(operatorCode)) {
            return;
        }
        approverVos.forEach(approverVo -> {
            if(operatorCode.equals(approverVo.getUserId())){
                approverVo.setUserId(turnToUserCode);
                approverVo.setUserName(userInfo == null ? "" : userInfo.getUserName());
                approverVo.setCreateTime(new Date());
                flowTaskInstApproverRepository.updateTaskInstApprovereById(approverVo);

            }
        });
    }

    @Override
    public ResponseResult batchTurnTasks(Task task, TurnTaskVo turnTaskVo) {
        if (StringUtils.isNotBlank(turnTaskVo.getComment())){
            this.addComment(task.getId(),turnTaskVo.getUserCode(),task.getProcessInstanceId(), CommentTypeEnum.ZB.getName(),turnTaskVo.getComment());
        }

        //1.转办任务
        taskService.setAssignee(task.getId(), turnTaskVo.getTurnToUserCode());
        if (StringUtils.isNotBlank(turnTaskVo.getUserCode())){
            taskService.setOwner(task.getId(), turnTaskVo.getUserCode());
            taskService.deleteUserIdentityLink(task.getId(), turnTaskVo.getUserCode(), CandidateTypeEnum.STA.getCode());
        }

        //如果在转办之前的操作是委派，则更新委派任务的处理人为转办后的人
        String parentTaskId = task.getParentTaskId();
        if (StringUtils.isNoneBlank(parentTaskId)){
            Task parentTask = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
            if (Objects.nonNull(parentTask)){
                //更新原委派人为转办后的人
                parentTask.setAssignee(turnTaskVo.getTurnToUserCode());
                taskService.saveTask(parentTask);
            }
        }

        //修改转办之后的操作人
        updateTaskTrace(task.getId(), turnTaskVo.getTurnToUserCode(),turnTaskVo.getUserCode());

        // 转办成功,同步更新该任务的处理人以及是否转办标识
        this.syncDataBySceneAndUser(turnTaskVo.getTaskId(), turnTaskVo.getTurnToUserCode(), Boolean.TRUE);
        return ResponseResult.success("转办成功");
    }

    /**
     * 按照场景根据任务实例ID同步新的处理人信息
     * @param taskId
     * @param userId
     */
    private void syncDataBySceneAndUser(String taskId, String userId, Boolean isTransfer) {
        List<String> taskIds = new ArrayList<>();
        taskIds.add(taskId);
        syncProcessTaskProcessor.syncDataBySceneAndUser(taskIds, userId, isTransfer);
    }
}
